package featuresWindows;

import helpFeaturesWindows.HelpPocketWindow;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import CAD.MainFrame;

import features.Block;
import features.Feature;
import features.RoundFloorPocket;
import j3d.J3D;
import visualCAD.RoundFloorPocketWindowView;

public class CreateRoundFloorPocket extends RoundFloorPocketWindowView implements ActionListener
{
	private J3D j3d = null;
	private PocketDinamicTopPanel pocketTopPanel;
	private PocketDinamicBottomPanel pocketBottomPanel;
	float  positionX = 0,
			positionY = 0,	
			positionZ = 0,
			r1,
			r2,
			r3,
			r4,
			radius,
			depth,
			width,
			length;
	public CreateRoundFloorPocket(J3D j3d, Block block)
	{
		super();
		
		this.j3d = j3d;
		
		pocketSplitPanel.setTopComponent(pocketTopPanel=new PocketDinamicTopPanel(
				positionX,positionY,
				radius,r1,r2,r3,r4,
				width,length));
		pocketSplitPanel.setBottomComponent(pocketBottomPanel=new PocketDinamicBottomPanel(
				positionX,positionZ,
				radius,r1,r2,r3,r4,
				depth,width,length));
		pocketSplitPanel.setDividerLocation(0.5);
		
		double y = pocketTopPanel.faceY;
		double x = pocketTopPanel.faceX;
		double z = pocketTopPanel.faceZ;
		redrawDynamicComponents();
		setVisible(true);
		pack();
		this.init();
		
	}
	private void redrawDynamicComponents(){
		positionX=(Float)xPositionSpinner.getValue();
		positionY=(Float)yPositionSpinner.getValue();
		positionZ=(Float)zPositionSpinner.getValue();
		depth=(Float)depthSpinner.getValue();
		try{
			if(sameRadiusCheckBox.isSelected()){
				r1=(Float)r1Spinner.getValue();
				r2=(Float)r1Spinner.getValue();
				r3=(Float)r1Spinner.getValue();
				r4=(Float)r1Spinner.getValue();
			}else{
				r1=(Float)r1Spinner.getValue();
				r2=(Float)r2Spinner.getValue();
				r3=(Float)r3Spinner.getValue();
				r4=(Float)r4Spinner.getValue();
			}
			radius=(Float)radiusSpinner.getValue();
			width=(Float)widthSpinner.getValue();
			length=(Float)lengthSpinner.getValue();
		}catch (Exception e) {
		//	e.printStackTrace();
			radius=((Double)radiusSpinner.getValue()).floatValue();
			if(sameRadiusCheckBox.isSelected()){
				r1=((Double)r1Spinner.getValue()).floatValue();
				r2=((Double)r1Spinner.getValue()).floatValue();
				r3=((Double)r1Spinner.getValue()).floatValue();
				r4=((Double)r1Spinner.getValue()).floatValue();
			}else{
				r1=((Double)r1Spinner.getValue()).floatValue();
				r2=((Double)r2Spinner.getValue()).floatValue();
				r3=((Double)r3Spinner.getValue()).floatValue();
				r4=((Double)r4Spinner.getValue()).floatValue();
			}
			width=((Double)widthSpinner.getValue()).floatValue();
			length=((Double)lengthSpinner.getValue()).floatValue();
		}
			setModels();
			pocketSplitPanel.setTopComponent(pocketTopPanel=new PocketDinamicTopPanel(
					positionX,positionY,
					radius,r1,r2,r3,r4,
					width,length));
			pocketSplitPanel.setBottomComponent(pocketBottomPanel=new PocketDinamicBottomPanel(
					positionX,positionZ,
					radius,r1,r2,r3,r4,
					depth,width,length));
			pocketSplitPanel.setDividerLocation(0.5);
	}
	void setModels(){
		
		SpinnerNumberModel lengthM = new SpinnerNumberModel(
				 ((Float)length).doubleValue(),((Float)(maiorRaio()*2)).doubleValue(),null,0.1);
		SpinnerNumberModel widthM = new SpinnerNumberModel(
				 ((Float)width).doubleValue(),((Float)(maiorRaio()*2)).doubleValue(),null,0.1);
		
		lengthSpinner.setModel(lengthM);
		widthSpinner.setModel(widthM);
		
		if(length<width){
			SpinnerNumberModel r1M = new SpinnerNumberModel(
					 ((Float)r1).doubleValue(),0,length/2,0.1);
			SpinnerNumberModel r2M = new SpinnerNumberModel(
					((Float)r2).doubleValue(),0,length/2,0.1);
			SpinnerNumberModel r3M = new SpinnerNumberModel(
					((Float)r3).doubleValue(),0,length/2,0.1);
			SpinnerNumberModel r4M = new SpinnerNumberModel(
					((Float)r4).doubleValue(),0,length/2,0.1);
			SpinnerNumberModel radiusM = new SpinnerNumberModel(
					((Float)radius).doubleValue(),0,length/2,0.1);
			
			r1Spinner.setModel(r1M);
			r2Spinner.setModel(r2M);
			r3Spinner.setModel(r3M);
			r4Spinner.setModel(r4M);
			radiusSpinner.setModel(radiusM);
			
		}else{
			SpinnerNumberModel r1M = new SpinnerNumberModel(
					 ((Float)r1).doubleValue(),0,width/2,0.1);
			SpinnerNumberModel r2M = new SpinnerNumberModel(
					((Float)r2).doubleValue(),0,width/2,0.1);
			SpinnerNumberModel r3M = new SpinnerNumberModel(
					((Float)r3).doubleValue(),0,width/2,0.1);
			SpinnerNumberModel r4M = new SpinnerNumberModel(
					((Float)r4).doubleValue(),0,width/2,0.1);
			SpinnerNumberModel radiusM = new SpinnerNumberModel(
					((Float)radius).doubleValue(),0,width/2,0.1);
			
			r1Spinner.setModel(r1M);
			r2Spinner.setModel(r2M);
			r3Spinner.setModel(r3M);
			r4Spinner.setModel(r4M);
			radiusSpinner.setModel(radiusM);
		}
		
	}
	float maiorRaio(){
		
		float retorno = r1;
		if(r1>r2)
			retorno=r1;
		else
			retorno=r2;
		if(retorno>r3)
			;
		else
			retorno=r3;
		if(retorno>r4)
			;
		else 
			retorno=r4;
		if(retorno>radius)
		return retorno;
		else
			return radius;
	}
	public void init()
	{
		this.okButton.addActionListener(this);
		helpButton.addActionListener(this);
		this.cancelButton.addActionListener(this);
		yPositionSpinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		zPositionSpinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		xPositionSpinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		depthSpinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		lengthSpinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		widthSpinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		radiusSpinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		r1Spinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		r2Spinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		r3Spinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		r4Spinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		sameRadiusCheckBox.addActionListener(this);
	}
	public void actionPerformed(ActionEvent event) 
	{
		Object origin = event.getSource();
		if (origin.equals(cancelButton))
		{
			this.cancel();
		} else if (origin.equals(okButton))
		{
			this.ok();
		}
		else if (origin.equals(sameRadiusCheckBox))
		{
			if(sameRadiusCheckBox.isSelected()){
				r2Spinner.setEnabled(false);
				r3Spinner.setEnabled(false);
				r4Spinner.setEnabled(false);
			} else{
				r2Spinner.setEnabled(true);
				r3Spinner.setEnabled(true);
				r4Spinner.setEnabled(true);
			}
		}
		else if (origin.equals(helpButton))
		{
			new HelpPocketWindow();
		}
	}
	private void ok()
	{
		if(sameRadiusCheckBox.isSelected()){
			RoundFloorPocket roundPocket = new RoundFloorPocket(
					Feature.ROUNDFLOORPOCKET, null,  length, 
					width, depth, 
					positionX,positionY, positionZ,
					r1, r1, r1, r1, radius, 
					this.nameTextField.getText(),MainFrame.Face);
		}else{
			RoundFloorPocket roundPocket = new RoundFloorPocket(
					Feature.ROUNDFLOORPOCKET, null,  length, 
					width, depth, 
					positionX,positionY, positionZ,
					r2, r1, r3, r4, radius, 
					this.nameTextField.getText(),MainFrame.Face);
		}
	
		this.j3d.removeSolid();
		this.j3d.addSolid(MainFrame.block.block);
		this.dispose();
	}
	private void cancel()
	{
		dispose();
	}
}
class PocketDinamicTopPanel extends JComponent{
	Shape pocket;
	Shape box;
	Shape axisX, axisY;
	double faceX = 0;
	double faceY = 0;
	double faceZ = 0;
	double multiplier= 0;
	double positionX,positionY, radius = 0, width=0, length=0;
	
	public PocketDinamicTopPanel(double positionX, double positionY, double radius,double r1,double r2,double r3,double r4, double width, double length) {
		super();
		findXandY();
		multiplier = calculateMultiplier();
		this.positionX = positionX;
		this.positionY = positionY;
		this.radius = radius;
		this.width= width;
		this.length=length;
		pocket=createPocket(multiplier*(positionX)+10,multiplier*(positionY)+20,multiplier*(radius),
				r1*multiplier,r2*multiplier,r3*multiplier,r4*multiplier,
				multiplier*width,multiplier*length);
		box=createRectangle();
		axisX = verticalLine();
		axisY = horizontalLine();
	}
	protected Shape createRectangle() {
		Shape rectangle = new Rectangle2D.Double(10,20,faceX*multiplier,faceY*multiplier);
		return rectangle;
	}
	protected Shape createPocket(double posX,double posY, double radius,
			double r1,double r2,double r3,double r4,
			double width, double length) {
		double posXL;
		double posYL;
		posXL = posX-length/2;
		posYL = posY-width/2;
		this.radius = radius;
		this.width= width;
		this.length=length;
		Area pocket = new Area(new Rectangle2D.Double(posXL+maior(r1,r4),posYL,length-maior(r1,r4)-maior(r2,r3),width));
		pocket.add(new Area(new Ellipse2D.Double(
				posXL,
				posYL+(width-2*r1),
				2*r1,
				2*r1)));
		pocket.add(new Area(new Ellipse2D.Double(
				posXL+(length-2*r2),
				posYL+width-2*r2,
				2*r2,
				2*r2)));
		pocket.add(new Area(new Ellipse2D.Double(
				posXL+(length-2*r3),
				posYL,
				2*r3,
				2*r3)));
		pocket.add(new Area(new Ellipse2D.Double(
				posXL,
				posYL,
				2*r4,
				2*r4)));
		pocket.add(new Area(new Rectangle2D.Double(
				posXL,
				posYL+r4,
				maior(r1,r4),
				width-r1-r4
		)));
		pocket.add(new Area(new Rectangle2D.Double(
				posXL+length-maior(r2,r3),
				posYL+r3,
				maior(r2,r3),
				width-r2-r3
		)));
		pocket.add(new Area(new Rectangle2D.Double(
				posXL+r1,
				posYL+width-menor(r1,r2),
				length-r1-r2,
				menor(r1,r2)
		)));
		pocket.add(new Area(new Rectangle2D.Double(
				posXL+r4,
				posYL,
				length-r4-r3,
				menor(r4,r3)
		)));
		
		return pocket;
	}
	double maior(double n1,double n2){
		if(n1>=n2)
			return n1;
		else
			return n2;
	}
	double menor(double n1,double n2){
		if(n1<=n2)
			return n1;
		else
			return n2;
	}
	protected Shape verticalLine() {
		
		Shape axisY = new Line2D.Double(10, 20, 10, 50);
		return axisY;
	}
	protected Shape horizontalLine(){
		Shape axisX = new Line2D.Double(10, 20, 50, 20);
		return axisX;
	}
	public void paint(Graphics g) {
		double translateX, translateY = 0;
		translateY = this.multiplier * faceY;
		Graphics2D g2 = (Graphics2D) g;
		g2.scale(1, -1);
		g2.translate(0, -215);
		g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
		
		g2.setPaint(new Color(211, 211, 211));
		g2.fill(box);
		g2.setPaint(new Color(135, 206, 250));
		g2.fill(pocket);
		g2.setPaint(Color.BLUE);
		g2.draw(pocket);
		g2.setPaint(Color.BLACK);
		g2.draw(box);
		g2.setPaint(Color.RED);
		g2.draw(axisX);
		g2.draw(axisY);
		g2.scale(1, -1);
		g2.drawString("X", 50 ,-10);
		int x = (int) (multiplier*(positionX));
		int y = (int) (multiplier*(positionY));
		g2.drawString("x", +x+8 ,-y-16);
		g2.drawString("Y", 0, -50);
	}

	private double calculateMultiplier() {
		double multiplier = 195/faceY;
		if(faceX*multiplier > 370){
			multiplier = 370/faceX;
		}
		if(faceZ*multiplier > 180){
			multiplier = 180/faceZ;
		}
		return multiplier;
	}
	private void findXandY() {
		switch(MainFrame.Face){
		case MainFrame.TOPFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.LOWERFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.FRONTFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.BACKFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.EASTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		case MainFrame.WESTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		}
	}
}
class PocketDinamicBottomPanel extends JComponent{
	
	Shape smallBox;
	Shape bigBox;
	Shape axisX, axisY;
	Shape[] centerLine= new Shape[5];
	double faceX = 0;
	double faceY = 0;
	double faceZ = 0;
	double multiplier= 0;
	
	
	private void findXandY() {
		switch(MainFrame.Face){
		case MainFrame.TOPFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.LOWERFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.FRONTFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.BACKFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.EASTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		case MainFrame.WESTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		}
	}
	private double calculateMultiplier() {
		double multiplier = 195/faceY;
		if(faceX*multiplier > 310){
			multiplier = 310/faceX;
		}
		if(faceZ*multiplier > 180){
			multiplier = 180/faceZ;
		}
		return multiplier;
	}
	
	public PocketDinamicBottomPanel(double positionX, double positionZ, 
			double radius,double r1,double r2,double r3,double r4,
			double depth, double width, double length) {
		super();
		findXandY();
		multiplier = calculateMultiplier();
		smallBox=createBox(multiplier*(positionX-length/2),multiplier*(-positionZ),multiplier*(length),multiplier*(depth));
		bigBox=createRectangle();
		axisX = verticalLine();
		axisY = horizontalLine();
		centerLine[0] = centerLine(10+multiplier*(r1+positionX-(length/2)), multiplier*(-positionZ), multiplier*(length), multiplier*(depth));
		centerLine[1] = centerLine(10+multiplier*(-r2+positionX+(length/2)), multiplier*(-positionZ), multiplier*(length), multiplier*(depth));
		centerLine[2] = centerLine(10+multiplier*(-r3+positionX+(length/2)), multiplier*(-positionZ), multiplier*(length), multiplier*(depth));
		centerLine[3] = centerLine(10+multiplier*(r4+positionX-(length/2)), multiplier*(-positionZ), multiplier*(length), multiplier*(depth));
		centerLine[4] = new Line2D.Double(10+multiplier*(positionX-(length/2)), 20+multiplier*(-positionZ+depth-radius), multiplier*(positionX+(length/2+0.1)), 20+multiplier*(-positionZ+depth-radius));
	}
	protected Shape createBox(double posX,double posY, double d1, double d2) {
		Shape rectangle = new Rectangle2D.Double(10+posX, 20+posY, d1, d2);
		return rectangle;
	}
	protected Shape createRectangle() {
		Shape rectangle = new Rectangle2D.Double(10,20,faceX*multiplier,faceZ*multiplier);
		return rectangle;
	}
	protected Shape verticalLine() {
		
		Shape axisY = new Line2D.Double(10, 20, 10, 50);
		return axisY;
	}
	protected Shape horizontalLine(){
		Shape axisX = new Line2D.Double(10, 20, 50, 20);
		return axisX;
	}
	protected Shape centerLine(double posX, double posY, double d1, double depth){
		Shape axisX = new Line2D.Double(posX, 20+posY, posX, 20+posY+depth);
		return axisX;
	}
	
	
	
	public void paint(Graphics g) {
		//System.out.println("translateY = " + translateY);
		Graphics2D g2 = (Graphics2D) g;
		g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
		float dash1[] = {2.5f, 2.5f};
		float dash2[] = {3f, 1.5f,1f,1.5f};
		
		g2.setPaint(new Color(211, 211, 211));
		g2.fill(bigBox);
		g2.setPaint(new Color(135, 206, 250));
		g2.fill(smallBox);
		g2.setPaint(Color.BLUE);
		g2.draw(centerLine[4]);
		g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, 
				BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f));
		g2.draw(smallBox);
		g2.setPaint(Color.BLACK);
		g2.setStroke(new BasicStroke());
		g2.draw(bigBox);
		g2.setPaint(Color.RED);
		g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, 
				BasicStroke.JOIN_MITER, 10.0f, dash2, 0.0f));
		g2.draw(centerLine[0]);
		g2.draw(centerLine[1]);
		g2.draw(centerLine[2]);
		g2.draw(centerLine[3]);
		g2.draw(axisX);
		g2.draw(axisY);
		g2.drawString("X", 50 ,20);
		g2.drawString("-Z", 0, 50);
	}
}

